#include "app.h"

#include <tbox/base/catch_throw.h>
#include <tbox/event/timer_event.h>
#include <tbox/terminal/terminal_nodes.h>
#include <tbox/terminal/helper.h>

namespace your {

void App::initShell() {
  using namespace tbox::terminal;

  auto shell = ctx().terminal();
  auto parent_node = shell->findNode("/");
  auto dir_node = shell->createDirNode();
  shell->mountNode(parent_node, dir_node, name());

  {
    auto func_node = shell->createFuncNode(
      [this](const Session &s, const Args) {
        s.send("Hello! This is cpp-tbox_sample.\r\n");
      },
      "hello");
    shell->mountNode(dir_node, func_node, "hello");
  }

  //! 这是原始的创建命令的方式
  {
    auto func_node = shell->createFuncNode(
      [this] (const Session &s, const Args &a) {
        if (a.size() == 2) {
          ros_->pubText(a[1]);
          s.send("done.\r\n");
        } else {
          s.send("usage: " + a[0] + " <text>\r\n");
        }
      },
      "publish text via ros topic");
    shell->mountNode(dir_node, func_node, "pub_text");
  }

  //! 这是使用tbox::terminal::StringFuncNodeProfile来创建命令的方式
  {
    tbox::terminal::StringFuncNodeProfile profile;
    profile.set_func = \
      [this](const std::string &text) {
        ros_->pubText(text);
        return true;
      };
    profile.help = "publish text via ros topic";
    tbox::terminal::AddFuncNode(*shell, dir_node, "pub_text_new", profile);
  }

  //! 这是创建命令的快捷方式
  tbox::terminal::AddFuncNode(*shell, dir_node, "enable_timer", [this] { timer_event_->enable(); });
  tbox::terminal::AddFuncNode(*shell, dir_node, "disable_timer", [this] { timer_event_->disable(); });

  //! 查看与修改counter的值
  tbox::terminal::AddFuncNode(*shell, dir_node, "count", count_);

  {
    auto func_node = shell->createFuncNode(
      [this] (const Session &s, const Args &a) {
        bool is_succ = false;
        std::ostringstream oss;

        if (a.size() == 3) {
          int a1, a2;
          if (!tbox::CatchThrow([&] {
            a1 = std::stoi(a[1]);
            a2 = std::stoi(a[2]);
          })) {
            is_succ = true;
            ros_->addTwoInt(a1, a2, [s](bool success, int sum) {
              std::ostringstream oss;
              if (success) {
                oss << "Result: " << sum << "\r\n";
              } else {
                oss << "Failed to add two integers.\r\n";
              }
              s.send(oss.str());
            });
          } else {
            oss << "Invalid integer input: " << a[1] << " or " << a[2] << "\r\n";
          }
        }
        if (!is_succ) {
          oss << "Usage: " << a[0] << " <a> <b>\r\n"
              << "Example: " << a[0] << " 1 2\r\n";
        }
        s.send(oss.str());
      },
      "add two int via ros service");
    shell->mountNode(dir_node, func_node, "add_two_ints");
  }
}

}
